﻿/*
 * Copyright (C) 2023 - 2024 lchfj.cn
 * 
 * This file is part of FastestHost.
 * 
 * FastestHost is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * FastestHost is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with FastestHost. If not, see <https://www.gnu.org/licenses/>.
 */

namespace Cn.Lchfj.FastestHost
{
    internal abstract class RunBase
    {
        protected RunSetting Setting { get; }
        protected RunBase(RunSetting setting)
        {
            Setting = setting;
        }


        protected virtual IReadOnlyList<string>? HostList { get; private set; }

        protected virtual IReadOnlyList<HostIP>? HostIpList { get; private set; }

        protected virtual IReadOnlyList<HostIPTestResult>? TestResultList { get; private set; }

        protected virtual IReadOnlyList<HostIP>? NewDataList { get; private set; }

        public virtual async Task RunAsync()
        {
            ConsoleHelper.WriteLine("正在获取需要检查的主机名······");
            HostList = await CreatHostListAsync();

            ConsoleHelper.WriteLine();
            HostIpList = await CreatHostIpListAsync();

            ConsoleHelper.WriteLine();
            TestResultList = await TestHostAsync();

            ConsoleHelper.WriteLine();
            await ReportTestResultAsync();

            ConsoleHelper.WriteLine();
            NewDataList = await LocalCheckHistory.CombineAsync(TestResultList);

            ConsoleHelper.WriteLine();
            await SaveToHostsFile();
        }

        protected virtual Task ReportTestResultAsync()
        {
            return Task.CompletedTask;
        }

        protected virtual async Task SaveToHostsFile()
        {
            ConsoleHelper.WriteLine($"正在修改Hosts文件···");

            var list = NewDataList ?? Array.Empty<HostIP>();
            await HostsFileChange.ChangeHosts(list);
        }

        protected virtual async Task<IReadOnlyList<HostIP>> CreatHostIpListAsync()
        {
            if (HostList is not { Count: > 0 })
            {
                ConsoleHelper.WriteLine("未成功获取主机名");
                return Array.Empty<HostIP>();
            }


            var nslookupReader = new NslookupReader();
            var list = new List<HostIP>();

            foreach (var host in HostList)
            {
                ConsoleHelper.WriteLine($"正在获取【{host}】对应的IP地址···");
                var ipList = await nslookupReader.ReadAsync(host);
                list.AddRange(ipList.Select(ip => new HostIP() { Host = host, IP = ip, IPFrom = 0 }));
            }

            return list;
        }

        protected virtual async Task<IReadOnlyList<HostIPTestResult>> TestHostAsync()
        {
            if (HostIpList is not { Count: > 0 })
            {
                ConsoleHelper.WriteLine("没有要进行测试的主机地址");
                return Array.Empty<HostIPTestResult>();
            }

            var list = new List<HostIPTestResult>();

            var groupList = from item in HostIpList
                            group item by item.Host into gro
                            select gro;

            var tester = new HostIPTest();
            foreach (var gro in groupList)
            {
                var container = new TestContainer(gro, tester);
                await container.WaitToEnd();
                list.AddRange(container.TestResult);
            }

            return list.ToList().AsReadOnly();
        }

        protected abstract Task<IReadOnlyList<string>> CreatHostListAsync();
    }
}